#ifndef LOGGERREGISTER_H_JM_20130121
#define LOGGERREGISTER_H_JM_20130121

#include <map>
#include <set>

#include "LogAppender.h"

namespace jmlib {
	/// Trieda predstavuje register loggerov, ktoreho funkcie je registracia 
	/// novych loggerov, aktivacia logerov a vytvaranie vazieb logger a 
	/// appender.
	/// Register je leakujuci singleton pretoze log zanika az s aplikaciou.
	class LoggerRegister {
	public:
		typedef std::set<LogAppender*> LogAppenderSet;

		/// Register loggerov je singleton a tato funkcia je pristupovy bod.
		static LoggerRegister* getInstance();

		/// Pridanie appenderu do logovacieho systemu.
		/// @param appenderName meno appenderu, pod ktory k nemu pristupuje user
		/// @param appender instancia appenderu, nad ktoru prevezme spravu 
		/// register
		void addAppender(const std::string& appenderName, LogAppender* appender);

		/// Pridanie loggeru do logovacieho systemu.
		/// @param loggerName meno loggeru, pod ktorym k nemu pristupuje user
		void addLogger(const std::string& loggerName) {
			LogAppenderSet* l = new LogAppenderSet();
			assignedAppendersByLogerName_[loggerName] = l;
			assignAppendersByLoggerName(loggerName, l);
		}

		/// Pridanie aktivatoru logu pre konkretny appender.
		/// @param activatorFilter filter, podla ktoreho sa budu aktivovat loggre
		/// @param appenderName appender, pre ktory sa budu aktivovat loggre
		/// (Pokial nie je zadany resp."" potom sa aplikuje pre vsetky appendre.)
		/// @param filtrationMethod urcuje sposob aplikacie filtra
		void addLoggerActivator(const std::string& activatorFilter, 
			const std::string& appenderName,
			LoggerActivatorFilter::FiltrationMethod filtrationMethod = 
			LoggerActivatorFilter::EXACT_MATCH);

		/// Iterator na zaciatok appendrov vyhradeny pre pouzitie konkretnym 
		/// loggerom.
		/// @param loggerName meno loggeru, ktory urcuje appendre
		LogAppenderSet::iterator getLogAppenderBegin(const std::string& loggerName);
		
		/// Iterator na koniec appendrov vyhradeny pre pouzitie konkretnym 
		/// loggerom.
		/// @param loggerName meno loggeru, ktory urcuje appendre
		LogAppenderSet::iterator getLogAppenderEnd(const std::string& loggerName);

	private:
		std::map<std::string, LogAppenderSet*> assignedAppendersByLogerName_;
		std::map<std::string, LogAppender*> allAppendersByAppenderName_;
		std::vector<LoggerActivatorFilter*> activationFilters_;

		/// Private konstuktor pretoze sa jedna o singleton
		LoggerRegister() { }
		/// Bez implementacie - singleton.
		LoggerRegister(const LoggerRegister&);
		/// Bez implementacie - singleton.
		LoggerRegister& operator=(const LoggerRegister&);

		/// Prirad dostupne appendre podla mena loggeru a kriterii pre aktivaciu.
		/// @param loggerName meno loggeru, pre ktory sa vyhladavaju appendre
		/// @param loggerAppenders vysledna mnozina appendrov naleziaca loggeru
		void assignAppendersByLoggerName(const std::string& loggerName, 
			LogAppenderSet* loggerAppenders);

		/// Prestavanie vsetkych priradeni appendrov k loggerom podla mena.
		/// Kazdemu loggeru sa zmazu appendre a novo sa priradia.
		void rebuildAssignedAppendersByLoggerName();

		
		/// Bezpecne najdenie mnoziny appendrerov pre logger podla mena loggeru.
		/// Pokial sa appender nenajde tak vrati prazdnu mnozinu (pre kazde 
		/// volnie rovnaku).
		LogAppenderSet* findAppendersByLoggerName(const std::string& loggerName);
	};	
} // namespace jmlib

#endif
